\documentclass{ctexart}

\usepackage{graphicx}
\usepackage{amsmath}

\title{五则运算计算器的实现}


 \author{胡宇梦 \\ 信息与计算科学　3210103435}


\begin{document}
\maketitle

\section{项目解读}
本项目的目标是实现一个五则运算计算器，能够完成简单的五则运算。
具体的功能要求有

1、用户输入的表达式为一个字符串，需要有一定的容错率，
能够忽略其中不属于数字, 小数点``.''，``+''，``-''，``$\ast$"，``/''，``\^{}''和空格的字符

2、 能够求解任意长度的表达式五则运算的结果
    

3、 能够允许浮点数计算和带括号计算


4、能够检测错误输入（包括但不限于表达式逻辑错误、除数为0）并给出错误信息

\section{设计思路}

本项目的程序整体流程是：首先绘制简单的图形界面，本程序有三个功能，
运算、清空屏幕、退出；用户进行计算的时候，输入一串字符串，
程序首先会读入字符串并存储在string对象exp中，其次过滤掉除运算符、
括号、数字、小数点之外的字符，然后进行表达式错误判断，
如果没有错误则将中缀表达式转换为后缀表达式postexp，
最后计算后缀表达式的结果并输出，如果表达式判断错误，则需要重新输入。
所以本程序重点功能在于运算，关于运算，本程序主要分为四个模块来实现：


1.读入字符串并存储在string对象。


2.去除无关字符。
本项目利用SaveChar函数，过滤掉不属于数字, 小数点``.''，``+''，``-''，``$\ast$"，``/''，``\^{}''和空格的字符。
本项目在这步还实现了若开头为“-”，则在表达式最前方添加“0”，实现了“负号”运算。


3.中缀表达式错误判断
本项目利用Error函数，判断去除无关字符后的表达式是否是合法的中缀表达式，若是合法表达式，返回0；
若不是合法表达式，则返回对应错误的值。本项目可检测以下7种错误：

（1）除数为0。比如：“100/0”


（2）括号不匹配。
比如：“4*(1+1))(”


（3）运算符或小数点连续出现。
	比如： “1..1+++1”


（4）开头或结尾是小数点或运算符。
比如：“+121-1”


（5）括号和数字之间缺少运算符。
比如： “2(1+1)”


（6）运算符和括号之间缺少操作数。
比如： “2(100+2\^{}3)”


（7）没有输入一个有效的数字和运算符。
比如:“aaaaaaaaa”

4.中缀表达式转换为后缀表达式
本项目利用TransmitExpression函数, 实现中缀表达式转换为后缀表达式。其中起主要作用的数据结构是创建的用来存放字符的栈。
此步骤的主要任务有处理操作数和处理运算符两个内容。
通过遍历去除无关字符后的表达式，若扫描到数字或者“.”，则将其存放到后缀表达式对应的string类型对象postexp中
若扫描到运算符，则入专门存放操作符的栈，如果栈外运算符的优先级大于栈内的优先级，直接让操作符入栈，继续扫描表达式的下一个元素;
如果栈外运算符的优先级小于栈内运算符的优先级，先让栈内的运算符放入到后缀表达式postexp中，然后将存放操作数的栈顶元素出栈一次，继续判断栈外运算符的优先级和栈内运算符的优先级，直到栈外大于栈内，然后入栈，继续扫描表达式的下一个元素;
如果栈外运算符的优先级等于栈内运算符的优先级，则直接将栈内
运算符出栈，继续扫描下一个元素。

5.计算后缀表达式的值
本项目利用函数EvaluateExpression计算后缀表达式的值。
其中起主要作用的数据结构是创建的用来存放数据的栈。
此步骤的主要任务有处理操作数和处理运算符两个内容。
通过遍历去除无关字符后的表达式，
若扫描到操作数，则将字符类型的操作数转换成double类型，然后直接入栈，若扫描到小数点，则先忽略，等整个小数的数字串都变成double类型后，再除以小数点对应的倍率，再入栈。
若扫描到运算符，则从操作数栈中弹出两个左右操作数，利用Operation函数进行运算， 将结果压入栈中。其中若出现除数为0的情况，则直接跳出EvaluateExpression，并报错。


\section{测试说明}
1. 程序使用方法：

程序编译通过后，键盘敲入a，即可进行表达式求值，每次计算前都需要键入a，即可继续输入表达式；
若需要情况屏幕，则输入b，若需要退出，则输入c。
\begin{figure}[ht]
    \centering
    \includegraphics[width=5cm]{1.jpg}
    \caption{计算器初始界面}
    \label{mode=1}
\end{figure} 

2. 参考算例检测：

Input1: 2\^{}(1+3)-5$\ast$(15.23)/(1+2)$\ast$3-5

input2：1.25+(3$\ast$(1+2\^{}2)$\ast$3-43)\^{}(4-2)

input3：2\^{}(1+3))-5$\ast$(15.23)/(1+2)$\ast$3-5

input4：2\^{}(1+3)-5$\ast$(15.23)/(1-1)$\ast$3-5
输出结果如下：可见功能正常使用
\begin{figure}[ht]
    \centering
    \includegraphics[width=6cm]{2.jpg}
    \caption{参考算例执行结果}
    \label{mode=1}
\end{figure} 


3. 错误检测

（1）除数为0:
100/(12-2$\ast$6)

（2）括号不匹配:
100/(12-2$\ast$6))

（3）运算符或小数点连续出现:
	100/(2$\ast$(1..7-(2$\ast$5.4+7.8)/3))

（4）开头或结尾是小数点或运算符:
+1213-123$\ast$4\^{}3

（5）括号和数字之前缺少运算符:
100/2(2$\ast$(1..7-(2$\ast$5.4+7.8)/3))

（6）运算符和括号之间缺少操作数:
2(100+2\^{}3)

（7）没有输入一个有效的数字和运算符:
Asdsafcfesdfsd

\begin{figure}[ht]
    \centering
    \includegraphics[width=8cm]{3.jpg}
    \caption{错误检测结果}
    \label{mode=1}
\end{figure} 


4. 功能检测


（1）不带括号的五则混合运算：
18.7-2$\ast$5.4+7.8/3+2\^{}3.2

（2）带一层括号的五则混合运算：
18.7-(2$\ast$5.4+7.8)/3\^{}2

（3）带多层括号的五则混合运算:
100/(2$\ast$(18.7\^{}2-(2$\ast$5.4+7.8)/3))

（4）混入无关字符:
10\&0/(2\^{}18.\%\%7-(2$\ast$5\$\#.4+\#\@7.8)!\~/3)

\begin{figure}[ht]
    \centering
    \includegraphics[width=8cm]{4.jpg}
    \caption{功能检测结果}
    \label{mode=1}
\end{figure} 

\end{document}
